using System;
using MbUnit.Framework;
using DotNetNukeMVPWizard.ProjectConfiguration;
using System.IO;
using System.Collections.Generic;

namespace DotNetNukeMVPWizard.Tests
{
    [TestFixture]
    public class TestMvpMultiProjectConfiguration : EnvironmentalDependencies
    {
        #region Properties
        private const string STR_Valid_IisAppRootUrl = STR_GoodLocalUrl + STR_TrailingUrlSlash;
        private const string STR_Valid_IisUrl = STR_Valid_IisAppRootUrl + @"DesktopModules/";
        private const string STR_Valid_Dependencies = STR_Valid_PathIisAppRootUrl + @"bin\";
        private const string STR_ParentProjectName = "Parent Project Name";
        private const string STR_SafeParentProjectName = "Parent_Project_Name";
        private const string STR_YourCompany = "Your Company";
        private const string STR_SafeYourCompany = "Your_Company";
        private const string STR_ProjectNamespaceName = "Project.NamespaceName";
        private MvpMultiProjectConfiguration Actual;
        #endregion

        #region SetUp
        [SetUp]
        public void SetUp()
        {
            Actual = new MvpMultiProjectConfiguration();
        }
        #endregion

        #region Test Methods
        [Test]
        [Description("Ensure that the IisAppRootUrl value can be set")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Merge_Placeholders_Into_Dictionary()
        {
            MakeConfigurationValid();
            Dictionary<string, string> replacementDictionary = new Dictionary<string,string>();
            Actual.FillDictionary(replacementDictionary);

            // TEST: Refactor tests to check the replacementdictionary has the key & value
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.IisUrl));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.IisAppRootUrl));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.PathIisAppRootUrl));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.Dependencies));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.DependenciesGallio));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.DependenciesMoq));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.DependenciesWatiN));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.ProjectNamespaceName));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.ParentProjectName));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.SafeParentProjectName));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.YourCompany));
            Assert.IsTrue(replacementDictionary.ContainsKey(MvpMultiProjectConfiguration.Keys.SafeYourCompany));
        }
        #endregion

        #region Test Properties
        // TODO: Add test for MvpMultiProjectConfiguration_Should_Build_ErrorMessages

        [Test]
        [Description("Ensure that the IisAppRootUrl value can be set")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Set_IisAppRootUrl()
        {
            Actual.SetIisAppRootUrl(STR_Valid_IisAppRootUrl);
            Assert.AreEqual(STR_Valid_IisAppRootUrl, Actual.IisAppRootUrl);
        }

        [Test]
        [Description("Ensure that the correct IisUrl is generated when setting the IisAppRootUrl")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Generate_IisUrl_From_IisAppRootUrl()
        {
            Actual.SetIisAppRootUrl(STR_Valid_IisAppRootUrl);
            Assert.AreEqual(STR_Valid_IisUrl, Actual.IisUrl);
        }

        [Test]
        [Description("Ensure that the IisUrl has a trailing slash")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Generate_IisUrl_With_Trailing_Slash()
        {
            Actual.SetIisAppRootUrl(STR_Valid_IisAppRootUrl);
            Assert.EndsWith(Actual.IisUrl, STR_TrailingUrlSlash);
        }

        [Test]
        [Description("Ensure that the IisUrl does not have a double trailing slash")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Generate_IisUrl_Without_Duplicate_Trailing_Slash()
        {
            Actual.SetIisAppRootUrl(STR_Valid_IisAppRootUrl);
            Assert.AreNotEqual(STR_TrailingUrlSlash + STR_TrailingUrlSlash, Actual.IisUrl.Substring(Actual.IisUrl.Length - 2));
        }

        [Test]
        [Description("Ensure that the PathIisAppRootUrl value can be set")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Set_PathIisAppRootUrl()
        {
            Actual.SetPathIisAppRootUrl(STR_Valid_PathIisAppRootUrl);
            Assert.AreEqual(STR_Valid_PathIisAppRootUrl, Actual.PathIisAppRootUrl, StringComparison.OrdinalIgnoreCase);
        }

        [Test]
        [Description("Ensure that the correct Dependencies path is generated when setting the PathIisAppRootUrl")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Generate_Dependencies_From_PathIisAppRootUrl()
        {
            Actual.SetPathIisAppRootUrl(STR_Valid_PathIisAppRootUrl);
            Assert.AreEqual(STR_Valid_Dependencies, Actual.Dependencies, StringComparison.OrdinalIgnoreCase);
        }

        [Test]
        [Description("Ensure that the path to Gallio is found if it exists")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Find_Likely_Path_To_Gallio()
        {
            if (Directory.Exists(STR_ValidPath_Gallio))
                Assert.AreEqual(STR_ValidPath_Gallio, Actual.DependenciesGallio, StringComparison.OrdinalIgnoreCase);
            else
                Assert.Inconclusive(String.Format("Test Pre-condition failed: Could not find Gallio at the expected path '{0}'", STR_ValidPath_Gallio));
        }

        [Test]
        [Description("Ensure that the path to Moq is found if it exists")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Find_Likely_Path_To_Moq()
        {
            if (Directory.Exists(STR_ValidPath_Moq))
                Assert.AreEqual(STR_ValidPath_Moq, Actual.DependenciesMoq, StringComparison.OrdinalIgnoreCase);
            else
                Assert.Inconclusive(String.Format("Test Pre-condition failed: Could not find Gallio at the expected path '{0}'", STR_ValidPath_Moq));
        }

        [Test]
        [Description("Ensure that the path to WatiN is found if it exists")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Find_Likely_Path_To_WatiN()
        {
            if (Directory.Exists(STR_ValidPath_WatiN))
                Assert.AreEqual(STR_ValidPath_WatiN, Actual.DependenciesWatiN, StringComparison.OrdinalIgnoreCase);
            else
                Assert.Inconclusive(String.Format("Test Pre-condition failed: Could not find Gallio at the expected path '{0}'", STR_ValidPath_WatiN));
        }

        [Test]
        [Description("Ensure that the ParentProjectName can be set")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Set_ParentProjectName()
        {
            Actual.SetParentProjectName(STR_ParentProjectName);
            Assert.AreEqual(STR_ParentProjectName, Actual.ParentProjectName);
        }

        [Test]
        [Description("Ensure that the correct SafeParentProjectName is generated when setting the ParentProjectName")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Generate_SafeParentProjectName_From_ParentProjectName()
        {
            Actual.SetParentProjectName(STR_ParentProjectName);
            Assert.AreEqual(STR_SafeParentProjectName, Actual.SafeParentProjectName);
        }

        [Test]
        [Description("Ensure that the YourCompany can be set")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Set_YourCompany()
        {
            Actual.SetYourCompany(STR_YourCompany);
            Assert.AreEqual(STR_YourCompany, Actual.YourCompany);
        }

        [Test]
        [Description("Ensure that the correct SafeYourCompany is generated when setting the YourCompany")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Generate_SafeYourCompany_From_YourCompany()
        {
            Actual.SetYourCompany(STR_YourCompany);
            Assert.AreEqual(STR_SafeYourCompany, Actual.SafeYourCompany);
        }

        [Test]
        [Description("Ensure that ProjectNameSpaceName can be set")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Set_ProjectNameSpaceName()
        {
            Actual.SetProjectNamespaceName(STR_ProjectNamespaceName);
            Assert.AreEqual(STR_ProjectNamespaceName, Actual.ProjectNamespaceName);
        }

        [Test]
        [Description("Ensure that the entire configuration is regarded as valid if all the IConfigurable items are valid")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Get_IsValid_True()
        {
            MakeConfigurationValid();
            Assert.IsTrue(Actual.IsValid);
        }

        // TODO: For code coverage sake, consider writing tests for the individual MvpMultiProjectConfiguration.IsValidzzz properties

        [Test]
        [Description("Ensure that an invalid YourCompany in the MvpMultiProjectConfiguration results in the entire configuration being regarded as invalid")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Get_IsValid_False_Without_YourCompany()
        {
            MakeConfigurationValid();
            Actual.SetYourCompany(string.Empty);
            Assert.IsFalse(Actual.IsValid);
        }

        [Test]
        [Description("Ensure that an invalid ProjectNamespaceName in the MvpMultiProjectConfiguration results in the entire configuration being regarded as invalid")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Get_IsValid_False_Without_ProjectNamespaceName()
        {
            MakeConfigurationValid();
            Actual.SetProjectNamespaceName(string.Empty);
            Assert.IsFalse(Actual.IsValid);
        }

        [Test]
        [Description("Ensure that an invalid ParentProjectName in the MvpMultiProjectConfiguration results in the entire configuration being regarded as invalid")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Get_IsValid_False_Without_ParentProjectName()
        {
            MakeConfigurationValid();
            Actual.SetParentProjectName(string.Empty);
            Assert.IsFalse(Actual.IsValid);
        }

        [Test]
        [Description("Ensure that an invalid PathIisAppRootUrl in the MvpMultiProjectConfiguration results in the entire configuration being regarded as invalid")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Get_IsValid_False_Without_PathIisAppRootUrl()
        {
            MakeConfigurationValid();
            Actual.SetPathIisAppRootUrl(string.Empty);
            Assert.IsFalse(Actual.IsValid);
        }

        [Test]
        [Description("Ensure that an invalid IisAppRootUrl in the MvpMultiProjectConfiguration results in the entire configuration being regarded as invalid")]
        [Annotation(Gallio.Model.AnnotationType.Info, "Owner: Dan Gilleland")]
        public void MvpMultiProjectConfiguration_Should_Get_IsValid_False_Without_IisAppRootUrl()
        {
            MakeConfigurationValid();
            Actual.SetIisAppRootUrl(string.Empty);
            Assert.IsFalse(Actual.IsValid);
        }

        private void MakeConfigurationValid()
        {
            Actual.SetYourCompany(STR_YourCompany);
            Actual.SetProjectNamespaceName(STR_ProjectNamespaceName);
            Actual.SetParentProjectName(STR_ParentProjectName);
            Actual.SetPathIisAppRootUrl(STR_Valid_PathIisAppRootUrl);
            Actual.SetIisAppRootUrl(STR_Valid_IisAppRootUrl);
        }
        #endregion
    }
}
